﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO.IsolatedStorage;
using System.Linq;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Input;
using tumblr.Api.Model;
using tumblr.Models;
using tumblr.Models.PostModel;

namespace tumblr.ViewModels
{
    public class SearchViewModel : ViewModelBase
    {
        private readonly Api.Blog _blogApi;

        #region Properties

        private string _query;
        public string Query
        {
            get
            {
                return _query;
            }
            set
            {
                if (_query != value)
                {
                    _query = value;
                    RaisePropertyChanged("Query");
                }
            }
        }

        private string _queryUrlHost;
        public string QueryUrlHost
        {
            get
            {
                return _queryUrlHost;
            }
            set
            {
                if (_queryUrlHost != value)
                {
                    _queryUrlHost = value;
                    RaisePropertyChanged("QueryUrlHost");
                }
            }
        }

        public ObservableCollection<SearchQuery> RecentQueryUrls { get; set; }

        private string _error;
        public string Error
        {
            get
            {
                return _error;
            }
            set
            {
                if (_error != value)
                {
                    _error = value;
                    RaisePropertyChanged("Error");
                }
            }
        }

        private bool _isSearching;
        public bool IsSearching
        {
            get
            {
                return _isSearching;
            }
            set
            {
                if (_isSearching != value)
                {
                    _isSearching = value;
                    RaisePropertyChanged("IsSearching");
                }
            }
        }

        private List<SearchQuery> SavedRecentSearches
        {
            get
            {
                if (!IsolatedStorageSettings.ApplicationSettings.Contains("recent-search"))
                    IsolatedStorageSettings.ApplicationSettings.Add("recent-search", new List<SearchQuery>());

                return IsolatedStorageSettings.ApplicationSettings["recent-search"] as List<SearchQuery>;
            }
        }

        #endregion

        public SearchViewModel()
        {
            _blogApi = new Api.Blog();

            SearchCommand = new DelegateCommand(Search, CanSearch);
            RecentQueryUrls = new ObservableCollection<SearchQuery>();
        }

        public override void LoadData()
        {
            foreach (var search in SavedRecentSearches.OrderByDescending(s => s.Timestamp))
            {
                RecentQueryUrls.Add(search);
            }

            IsDataLoaded = true;
        }

        #region SearchCommand

        public ICommand SearchCommand { get; private set; }

        private void Search(object parameter)
        {
            BeginSearching();

            var queryUrl = TryMapQueryToUrl();
            if (queryUrl == null)
            {
                EndSearching();
                return;
            }

            QueryUrlHost = queryUrl.Host;

            _blogApi.GetPosts(QueryUrlHost, ShowResults);
        }

        private bool CanSearch(object parameter)
        {
            if (string.IsNullOrWhiteSpace(Query))
                return false;

            var key = (Key)(Enum.Parse(typeof(Key), parameter.ToString(), false));
            return (key == Key.Enter);
        }

        private void BeginSearching()
        {
            QueryUrlHost = string.Empty;
            Error = string.Empty;

            App.AllPostsViewModel.Title = string.Empty;
            App.AllPostsViewModel.Posts.Clear();

            IsSearching = true;
        }

        private void EndSearching()
        {
            IsSearching = false;
        }

        private void SaveQueryUrl()
        {
            if (SavedRecentSearches.Any(s => string.Equals(s.Query, QueryUrlHost, StringComparison.InvariantCultureIgnoreCase)))
                return;

            var avatarUrl = string.Format("http://api.tumblr.com/v2/blog/{0}/avatar/", QueryUrlHost);
            var searchQuery = new SearchQuery { Query = QueryUrlHost, Timestamp = DateTime.UtcNow, AvatarUrl = avatarUrl };
            SavedRecentSearches.Add(searchQuery);

            RecentQueryUrls.Insert(0, searchQuery);
        }

        private Uri TryMapQueryToUrl()
        {
            Uri queryUrl = null;

            if (!Query.StartsWith("http"))
            {
                if (!Regex.IsMatch(Query, @"\.[^.\s]*$"))
                    if (Uri.TryCreate(string.Format("http://{0}.tumblr.com", Query), UriKind.Absolute, out queryUrl))
                        return queryUrl;

                if (Uri.TryCreate(string.Format("http://{0}", Query), UriKind.Absolute, out queryUrl))
                    return queryUrl;
            }

            if (Uri.TryCreate(Query, UriKind.Absolute, out queryUrl))
                return queryUrl;

            return queryUrl;
        }

        private void ShowResults(Response response)
        {
            EndSearching();
            SaveQueryUrl();
            Query = string.Empty;

            Deployment.Current.Dispatcher.BeginInvoke(() =>
            {
                App.AllPostsViewModel.Title = response.blog.title;

                foreach (var post in response.posts)
                {
                    var p = PostModelFactory.Create(post);
                    App.AllPostsViewModel.Posts.Add(p);
                }

                (App.Current as App).RootFrame.Navigate(Views.Views.ALL_POSTS_PAGE);
            });
        }

       
        #endregion
    }
}
